import { ElLoading, type LoadingOptions } from 'element-plus'
import { type Directive, nextTick, onBeforeUnmount, ref } from 'vue'
import 'element-plus/theme-chalk/src/loading.scss'

export function useDefineLoading(options: Omit<LoadingOptions, 'target' | 'body' | 'customClass'> = {}) {
  const els = ref<Set<HTMLElement> | null>(new Set([]))
  const loadings: any[] = []
  const showLoading = async () => {
    await nextTick()
    if (!els.value)
      return;
    [...els.value].forEach((el: HTMLElement) => {
      const loading = ElLoading.service({
        target: el || document.documentElement,
        customClass: 'global-loading',
        // 6-dots-rotate
        svg: `
          <g><circle cx="12" cy="2.5" r="1.5" fill="currentColor" opacity="0.14"/><circle cx="16.75" cy="3.77" r="1.5" fill="currentColor" opacity="0.29"/><circle cx="20.23" cy="7.25" r="1.5" fill="currentColor" opacity="0.43"/><circle cx="21.5" cy="12" r="1.5" fill="currentColor" opacity="0.57"/><circle cx="20.23" cy="16.75" r="1.5" fill="currentColor" opacity="0.71"/><circle cx="16.75" cy="20.23" r="1.5" fill="currentColor" opacity="0.86"/><circle cx="12" cy="21.5" r="1.5" fill="currentColor"/><animateTransform attributeName="transform" calcMode="discrete" dur="1s" repeatCount="indefinite" type="rotate" values="0 12 12;30 12 12;60 12 12;90 12 12;120 12 12;150 12 12;180 12 12;210 12 12;240 12 12;270 12 12;300 12 12;330 12 12;360 12 12"/></g>
        `,
        // eclipse
        // svg: `
        //   <path fill="currentColor" d="M2,12A11.2,11.2,0,0,1,13,1.05C12.67,1,12.34,1,12,1a11,11,0,0,0,0,22c.34,0,.67,0,1-.05C6,23,2,17.74,2,12Z"><animateTransform attributeName="transform" dur="1s" repeatCount="indefinite" type="rotate" values="0 12 12;360 12 12"/></path>
        // `,
        svgViewBox: '0 0 24 24',
        ...options,
      })
      loadings.push(loading)
    })
  }
  const hideLoading = () => {
    if (loadings && loadings.length > 0) {
      loadings.forEach((l: any) => l?.close?.())
    }
  }
  /** 指令 */
  const vLoading: Directive<HTMLElement> = (_el) => {
    if (!els.value)
      return
    els.value.add(_el)
  }
  /** */
  const withLoading = <T extends (...args: any[]) => any>(func: T) => {
    const newFunc = (...params: Parameters<T>): Promise<ReturnType<T>> => {
      // eslint-disable-next-line no-async-promise-executor
      return new Promise(async (resolve) => {
        showLoading()
        const result = await func(...params)
        resolve(result)
        hideLoading()
      })
    }
    return newFunc
  }
  /** 销毁函数 */
  const destroy = async () => {
    if (!els.value)
      return
    if (els.value.size === 0)
      return
    hideLoading()
    await nextTick()
    els.value = null
  }

  /** 离开页面销毁 */
  onBeforeUnmount(destroy)
  return { vCustomLoading: vLoading, withLoading, destroy }
}
